// Tree.cpp: implementation of the Tree class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Tree.h"
#include "Hash.h"
#include "NoteParamManagerFactory.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

namespace PDMS
{
	namespace PDMSFrame
	{
		UE_IMPLEMENT_DYNAMIC( UeDbObject, PersistentObject );
		
		UeDbObject::UeDbObject()
		{
			m_pHash = NULL;
		}
		
		UeDbObject::UeDbObject( const UeDbObject& obj ):
					Persistable( obj )
		{
			m_strName = obj.m_strName;
			m_strDescription = obj.m_strDescription;
			m_pHash = obj.m_pHash;
			m_arSubTree = obj.m_arSubTree;
		}

		UeDbObject::~UeDbObject()
		{
			
		}

		UESoft::ErrorStatus UeDbObject::Add( Tree* pTree )
		{
			AssertWriteEnable();

			ASSERT( pTree );
			ASSERT( m_pHash );
			
			UESoft::ErrorStatus es = UESoft::eOk;

			if ( pTree->Name().IsEmpty() )
			{
				pTree->Name( AutoName() );
			}
			es = m_pHash->Add( pTree );
			if( es != UESoft::eOk )
			{
				ASSERT( es != UESoft::eOk );
				return es;
			}

			ASSERT( !pTree->Id().IsNull() );
			m_arSubTree.push_back( pTree->Id() );
			pTree->HashModel( m_pHash );
			pTree->Parent( Id() );
			
			return UESoft::eOk;
		}

		StdString UeDbObject::AutoName() const
		{			
			StdString strTemp;
			strTemp.Format( _T("%d"), m_arSubTree.size() + 1 );
			return strTemp;
		}

		UESoft::ErrorStatus UeDbObject::Parent( UeDbObject*& pObj, UeDb::OpenModel om ) const
		{
			AssertReadEnable();
			ASSERT( m_pHash );

			return m_pHash->GetTree( OwnerId() , pObj, om );
		}

		void UeDbObject::RemoveAll()
		{
			AssertWriteEnable();

			m_arSubTree.clear();
		}
		
		UESoft::ErrorStatus UeDbObject::iterator::Get( UeDbObject*& pTree, UeDb::OpenModel om) 
		{
			if ( m_pTree == NULL || end() )
			{
				pTree = NULL;
				return UESoft::eIteratorDone;
			}
			ASSERT( m_pTree->m_pHash != NULL );
			return m_pTree->m_pHash->GetTree( *m_it, pTree, om );
		}
		
		UeDbObject::iterator UeDbObject::iterator::operator++(int)
		{
			ASSERT( !end() );
			
			m_it++;
			if ( !m_skipDeleted )
				return *this;

			if ( end() )
				return *this;

			UeDbObject* pTemp = NULL;
			UESoft::ErrorStatus es = Get( pTemp );
			if ( es == UESoft::eOk )
			{
				if ( pTemp->IsDeleteState() )
				{
					pTemp->Close();
					return (*this)++;
				}
				pTemp->Close();
			}
			ASSERT( es == UESoft::eOk );

			return *this;
		}

		UESoft::ErrorStatus UeDbObject::SetParam()
		{
			NoteParamIF * pIF = NoteParamManagerFactory::Instance()->GetNoteParamManager()
				->CreateObject( this->GetRuntimeClass() );
			if ( pIF == NULL )
				return UESoft::eNotExistObjectParamClass;

			UESoft::ErrorStatus es = pIF->Show( this );
			return es;
		}
		
		UeDbObject::iterator::iterator( const Tree* pTree, BOOL atBeginning, BOOL skipDeleted ):
		m_pTree( pTree )
		{
			ASSERT( pTree );
			m_skipDeleted = skipDeleted;
			if ( atBeginning )
			{
				m_it = m_pTree->m_arSubTree.begin();
				if ( !m_skipDeleted || end() )
					return;
				
				UeDbObject* pTemp = NULL;
				UESoft::ErrorStatus es = Get( pTemp );
				if ( es == UESoft::eOk )
				{
					if ( pTemp->IsDeleteState() )
					{
						pTemp->Close();
						(*this)++ ;
						return;
					}
					pTemp->Close();
					return;
				}
				ASSERT( es == UESoft::eOk );

			}
			else
				m_it = m_pTree->m_arSubTree.end();
		}

		
		void UeDbObject::Name( const StdString& strName ) {
			AssertWriteEnable();
			StdString strTemp = strName;
			if ( strTemp.IsEmpty() && !OwnerId().IsNull() )
			{
				UeDbObject* pObj = NULL;
				UESoft::ErrorStatus es = Parent( pObj, UeDb::eForRead );
				ASSERT( es == UESoft::eOk );
				strTemp = pObj->AutoName();
				pObj->Close();
			}
			if ( m_pHash != NULL && m_strName != strTemp )
			{
				m_pHash->NameChange( Id(), m_strName, strTemp );
			}
			m_strName = strTemp;
		}
			
		UESoft::ErrorStatus UeDbObject::SetDelete()
		{
			UESoft::ErrorStatus es = UESoft::eOk;
			es = Persistable::SetDelete();
			if ( es != UESoft::eOk )
				return es;

			UeDbObject* pTemp = NULL;

			iterator it;
			for ( it = this->Iterator(); !it.end(); it++ )
			{
				es = it.Get( pTemp );
				if ( es == UESoft::eOk )
				{
					es = pTemp->SetDelete();
					pTemp->Close();
					if ( es != UESoft::eOk )
						return es;

					continue;
				}
				return es;
			}
			return UESoft::eOk;
		}
	}
}
